package com.hd.controller.activiti;

import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletResponse;

import com.hd.entity.activiti.CommentEntity;
import com.hd.service.activiti.CommentEntityService;
import org.activiti.engine.ActivitiObjectNotFoundException;
import org.activiti.engine.ActivitiTaskAlreadyClaimedException;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.hd.commons.shiro.ShiroUser;
import com.hd.controller.base.BaseController;
import com.hd.entity.activiti.ElementDef;
import com.hd.entity.activiti.UserTask;
import com.hd.entity.sys.User;
import com.hd.service.activiti.ActivitiService;
import com.hd.service.activiti.ElementDefService;
import com.hd.service.activiti.UserTaskService;
import com.hd.util.result.Result;

/**
 * 任务
 */
@Controller
@RequestMapping("/task")
public class TaskController extends BaseController{
    @Autowired
    private UserTaskService userTaskService;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private HistoryService historyService;
    @Autowired
    private ActivitiService activitiService;
    @Autowired
    private ElementDefService elementDefService;
    @Autowired
	private CommentEntityService commentEntityService;
  
    /**
     * 初始化任务节点信息
     * @return
     */
    @RequestMapping("initialization")
    @ResponseBody
    public Object initialization(){
    	userTaskService.initTaskNode();
        return renderSuccess("初始化成功！");
    }

    /**
     * 初始化单个的bpmn
     * @param processDefinitionId
     * @return
     */
    @RequestMapping("loadSingleBpmn")
    @ResponseBody
    public Object loadSingleBpmn(String processDefinitionId){
    	userTaskService.loadSingleBpmn(processDefinitionId);
        return renderSuccess("初始化成功！");
    }

  
   

    /**
     * 查询当前流程图 单实例待办用到的
     * @param taskId
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping("/showHisCurrentView/{taskId}")
    public ModelAndView showHisCurrentView(@PathVariable("taskId") String taskId,HttpServletResponse response)throws Exception{
        ModelAndView mav=new ModelAndView();
        HistoricTaskInstance hti=historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
        String processDefinitionId=hti.getProcessDefinitionId(); // 获取流程定义id
        ProcessDefinition processDefinition=repositoryService.createProcessDefinitionQuery() // 创建流程定义查询
                .processDefinitionId(processDefinitionId) // 根据流程定义id查询
                .singleResult();
        mav.addObject("deploymentId",processDefinition.getDeploymentId()); // 部署id
        mav.addObject("diagramResourceName", processDefinition.getDiagramResourceName()); // 图片资源文件名称

        ProcessDefinitionEntity	processDefinitionEntity=(ProcessDefinitionEntity) repositoryService.getProcessDefinition(processDefinitionId);
        String processInstanceId=hti.getProcessInstanceId(); // 获取流程实例id
        ProcessInstance pi=runtimeService.createProcessInstanceQuery() // 根据流程实例id获取流程实例
                .processInstanceId(processInstanceId)
                .singleResult();
        ActivityImpl activityImpl=processDefinitionEntity.findActivity(pi.getActivityId()); // 根据活动id获取活动实例
        mav.addObject("x", activityImpl.getX()); // x坐标
        mav.addObject("y", activityImpl.getY()); // y坐标
        mav.addObject("width", activityImpl.getWidth()); // 宽度
        mav.addObject("height", activityImpl.getHeight()); // 高度
        mav.setViewName("jsp/activiti/task/currentView");
        return mav;
    }

	/**
	 * 多实例流程追踪图
	 * @param processInstanceId
	 * @param response
	 * @return
	 * @throws Exception
	 */
	@RequestMapping("/showHisCurrentViewMulti/{processInstanceId}")
	public ModelAndView showHisCurrentViewMulti(@PathVariable("processInstanceId") String processInstanceId,HttpServletResponse response)throws Exception{
		ModelAndView mav=new ModelAndView();
		HistoricTaskInstance hti=historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).singleResult();
		String processDefinitionId=hti.getProcessDefinitionId(); // 获取流程定义id
		ProcessDefinition processDefinition=repositoryService.createProcessDefinitionQuery() // 创建流程定义查询
				.processDefinitionId(processDefinitionId) // 根据流程定义id查询
				.singleResult();
		mav.addObject("deploymentId",processDefinition.getDeploymentId()); // 部署id
		mav.addObject("diagramResourceName", processDefinition.getDiagramResourceName()); // 图片资源文件名称

		ProcessDefinitionEntity	processDefinitionEntity=(ProcessDefinitionEntity) repositoryService.getProcessDefinition(processDefinitionId);
		ProcessInstance pi=runtimeService.createProcessInstanceQuery() // 根据流程实例id获取流程实例
				.processInstanceId(processInstanceId)
				.singleResult();
		List<Task>tasks=taskService.createTaskQuery().processInstanceId(processInstanceId).list();
		for(Task task:tasks){
			task.getExecutionId();
		}
		ActivityImpl activityImpl=processDefinitionEntity.findActivity(pi.getActivityId()); // 根据活动id获取活动实例
		mav.addObject("x", activityImpl.getX()); // x坐标
		mav.addObject("y", activityImpl.getY()); // y坐标
		mav.addObject("width", activityImpl.getWidth()); // 宽度
		mav.addObject("height", activityImpl.getHeight()); // 高度
		mav.setViewName("jsp/activiti/task/currentView");
		return mav;
	}
    /**
     * 查看流程图
     * @param deploymentId
     * @param diagramResourceName
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping("/showView")
    public String showView(String deploymentId,String diagramResourceName,HttpServletResponse response)throws Exception{
        InputStream inputStream=repositoryService.getResourceAsStream(deploymentId, diagramResourceName);
        OutputStream out=response.getOutputStream();
        for(int b=-1;(b=inputStream.read())!=-1;){
            out.write(b);
        }
        out.close();
        inputStream.close();
        return null;
    }
    
    /**
     * 签收任务
     * @param taskId
     * @return
     */
    @ResponseBody
    @RequestMapping("/claim/{taskId}")
    public Object claim(@PathVariable("taskId")String taskId,String userId) {
    	Result result=new Result();
    	try {
			User user=new User();
			user.setId(userId);
			this.activitiService.doClaim(user, taskId);
			result.setSuccess(Boolean.TRUE);
			result.setMsg("任务签收成功！");
		}catch (ActivitiObjectNotFoundException e){
			result.setSuccess(Boolean.FALSE);
			result.setMsg("此任务不存在！任务签收失败！");
		}catch (ActivitiTaskAlreadyClaimedException e) {
			result.setSuccess(Boolean.FALSE);
			result.setMsg("此任务已被其他组成员签收！请刷新页面重新查看！");
		}catch (Exception e) {
			result.setSuccess(Boolean.FALSE);
			result.setMsg("任务签收失败！请联系管理员！");
		} 
    	return result;
    }
    /**
     * 签收任务
     * @param taskId
     * @return
     */
    @ResponseBody
    @RequestMapping("/unclaim/{taskId}")
    public Object unclaim(@PathVariable("taskId")String taskId) {
    	Result result=new Result();
    	try {
			this.activitiService.doUnClaim(taskId);
			result.setSuccess(Boolean.TRUE);
			result.setMsg("任务反签收成功！");
		}catch (ActivitiObjectNotFoundException e){
			result.setSuccess(Boolean.FALSE);
			result.setMsg("此任务不存在！任务反签收失败！");
		}
    	return result;
    }

    /**
	 * 委派任务
	 * 委派也是代办、协办，你领导接到一个任务，让你代办，你办理完成后任务还是回归到你的领导，事情是你做的，功劳是你领导的，这就是代办。
	 * 所以代办人完成任务后，任务还会回到原执行人，流程不会发生变化。
	 * @param taskId	
	 * @param userId 代办人
	 * @return
	 */
	@RequestMapping(value = "/delegateTask/{taskId}")
	@ResponseBody
	public Result delegateTask(@PathVariable("taskId") String taskId, @RequestParam("userId") String userId){
		Result result = new Result();
		try {
			this.activitiService.doDelegateTask(userId, taskId);
			result.setSuccess(Boolean.TRUE);
			result.setMsg("委派任务成功！");
		} catch (ActivitiObjectNotFoundException e){
			result.setSuccess(Boolean.FALSE);
			result.setMsg("此任务不存在！委派任务失败！");
		} catch (Exception e) {
			result.setSuccess(Boolean.FALSE);
			result.setMsg("委派任务失败，系统错误！");
		}
		return result;
	}
	
	/**
	 * 转办任务，办理完成后，流程会继续向下走。
	 * @param taskId
	 * @param userId
	 * @return
	 */
	@RequestMapping(value = "/transferTask/{taskId}")
	@ResponseBody
	public Object transferTask(@PathVariable("taskId") String taskId, @RequestParam("userId") String userId){
		Result result = new Result();
		try {
			this.activitiService.doTransferTask(userId, taskId);
			result.setSuccess(Boolean.TRUE);
			result.setMsg("转办任务成功！");
		} catch (ActivitiObjectNotFoundException e){
			result.setSuccess(Boolean.FALSE);
			result.setMsg("此任务不存在！委派任务失败！");
		} catch (Exception e) {
			result.setSuccess(Boolean.FALSE);
			result.setMsg("转办任务失败，系统错误！");
		}
		return result;
	}
	
	/**
	 * 撤销任务
	 * @return
	 * @throws Exception 
	 */
	@RequestMapping("/revoke/{taskId}/{processInstanceId}")
	@ResponseBody
	public Object revoke(@PathVariable("taskId") String taskId, @PathVariable("processInstanceId") String processInstanceId) throws Exception{
		Result result = new Result();
		try {
			User user=new User();
			user.setId(getUserId());
			Integer revokeFlag = this.activitiService.revoke(taskId, processInstanceId,user);
//			Integer revokeFlag = this.revokeTaskService.revoke(taskId, processInstanceId);
//			Command<Integer> cmd = new RevokeTask(taskId, processInstanceId);
//			Integer revokeFlag = this.processEngine.getManagementService().executeCommand(cmd);
			
			
			if(revokeFlag == 0){
				result.setSuccess(Boolean.TRUE);
				result.setMsg("撤销任务成功！");
			}else if(revokeFlag == 1){
				result.setSuccess(Boolean.FALSE);
				result.setMsg("撤销任务失败 - [ 此审批流程已结束! ]");
			}else if(revokeFlag == 2){
				result.setSuccess(Boolean.FALSE);
				result.setMsg("撤销任务失败 - [ 下一结点已经通过,不能撤销! ]");
			}
		} catch (Exception e) {
			result.setSuccess(Boolean.FALSE);
			result.setMsg("撤销任务失败 - [ 内部错误！]");
			throw e;
		}
		return result;
	}
	
	  /**
     * 激活、挂起流程定义-根据processDefinitionId
     * @param status
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/updateProcessStatusByProDefinitionId")
    @ResponseBody
    public Result updateProcessStatusByProDefinitionId(
    		@RequestParam("status") String status,
    		@RequestParam("processDefinitionId") String processDefinitionId) throws Exception{
    	Result result = new Result();
    	if (status.equals("active")) {
            repositoryService.activateProcessDefinitionById(processDefinitionId, true, null);
            result.setSuccess(Boolean.TRUE);
            result.setMsg("已激活ID为[" + processDefinitionId + "]的流程定义。");
        } else if (status.equals("suspend")) {
            repositoryService.suspendProcessDefinitionById(processDefinitionId, true, null);
            result.setSuccess(Boolean.TRUE);
            result.setMsg("已挂起ID为[" + processDefinitionId + "]的流程定义。");
        }
    	return result;
    }
    
    /**
     * 激活、挂起流程实例-根据processInstanceId
     * @param status
     * @param processInstanceId
     * @param redirectAttributes
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/updateProcessStatusByProInstanceId/{status}/{processInstanceId}")
    @ResponseBody
    public Object updateProcessStatusByProInstanceId(
    		@PathVariable("status") String status, 
    		@PathVariable("processInstanceId") String processInstanceId,
            RedirectAttributes redirectAttributes) throws Exception{
    	Result result = new Result();
    	if (status.equals("active")) {
    		this.activitiService.activateProcessInstance(processInstanceId);
//          redirectAttributes.addFlashAttribute("message", "已激活ID为[ " + processInstanceId + " ]的流程实例。");
    		result.setSuccess(Boolean.TRUE);
            result.setMsg("已激活ID为[" + processInstanceId + "]的流程实例。");
    	} else if (status.equals("suspend")) {
        	this.activitiService.suspendProcessInstance(processInstanceId);
//          redirectAttributes.addFlashAttribute("message", "已挂起ID为[ " + processInstanceId + " ]的流程实例。");
        	result.setSuccess(Boolean.TRUE);
            result.setMsg("已挂起ID为[" + processInstanceId + "]的流程实例。");
    	}
    	return result;
    }
    
    /**
     * 初始化跳转节点
     * @param model
     * @param procDefId
     * @param taskDefKey
     * @param flag 
     * flag=flase 向前跳转
     * flag=true 向后跳转
     * @return
     */
    @RequestMapping("/initJumpTaskNodes")
    public String initJumpTaskNodes(Model model,String procDefId,String taskDefKey,Boolean flag) {
    	 List<ElementDef> elementDefs=new ArrayList<ElementDef>();
    	if(flag) {
    		elementDefs = elementDefService.getNextElementDefs(procDefId, taskDefKey);
    	}else {
    		elementDefs=elementDefService.getPrevElementDefs(procDefId, taskDefKey);
    	}
    	model.addAttribute("elementDefs", elementDefs);
    	model.addAttribute("flag",flag);
		return "jsp/activiti/deploy/taskNodes";
    }
    /**
	 * 跳转（包括回退和向前）至指定活动节点
     * @throws Exception 
	 */
    @ResponseBody
    @RequestMapping("/jumpTask")
	public Object JumpTask(String currentTaskId, String targetTaskDefinitionKey,String comment,Boolean flag) throws Exception {
    	Task task=taskService.createTaskQuery().taskId(currentTaskId).singleResult();
    	String taskKey=task.getTaskDefinitionKey();
    	String processDefinitionId=task.getProcessDefinitionId();
    	ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
    	String proceDefKey=processDefinition.getKey();
    	UserTask userTask = userTaskService.getUserTaskByParams(proceDefKey,taskKey);
    	String taskCategory=userTask.getTaskCategory();
    	if(taskCategory==null || taskCategory.equals("0")) {
    		//单任务跳转
    		activitiService.moveTo(currentTaskId, targetTaskDefinitionKey);
    	}else {
    		if(taskCategory.equals("1")) {
    			//并行节点跳转
    			activitiService.paralleMoveTo(currentTaskId, targetTaskDefinitionKey);
    		}
    		if(taskCategory.equals("2")) {
    			//多实例跳转
    			activitiService.multiInstanceMoveTo(currentTaskId, targetTaskDefinitionKey);
    		}
    	}
		//保存跳转信息
		saveJumpTaskInfo(task,targetTaskDefinitionKey,flag,comment);
		return renderSuccess("跳转成功！");
	}

	protected void saveJumpTaskInfo(Task task,String targetTaskDefinitionKey,Boolean flag,String content){
		CommentEntity commentEntity=new CommentEntity();
		commentEntity.setUserid(getUserId());
		commentEntity.setUserName(getStaffName());
		commentEntity.setTime(new Date());
		commentEntity.setTaskId(task.getId());
		commentEntity.setTaskName(task.getName());
		String proceDefId=task.getProcessDefinitionId();
		commentEntity.setProcessInstanceId(task.getProcessInstanceId());
		ElementDef elementDef=elementDefService.findByParams(proceDefId,targetTaskDefinitionKey);
		String comment="";
		if(flag){
			commentEntity.setType(CommentEntity.COMMENT_MOVENEXT);
			comment="从【"+task.getName()+"】任务向前跳转到【"+elementDef.getName()+"】任务!跳转原因:"+content;
		}else{
			commentEntity.setType(CommentEntity.COMMENT_MOVEPREV);
			comment="从【"+task.getName()+"】任务回退跳转到【"+elementDef.getName()+"】任务!跳转原因:"+content;
		}
		commentEntity.setComment(comment);
		commentEntityService.save(commentEntity);
	}

	/**
	 * 查询操作记录
	 * @param processInstanceId 流程实例ID
	 * @param model
	 * @return
	 */
	@RequestMapping("/queryOperatorRecords/{processInstanceId}")
	public String queryOperatorRecords(@PathVariable("processInstanceId") String processInstanceId,Model model){
		List<CommentEntity>commentEntities=commentEntityService.findByProcessInstanceId(processInstanceId);
		model.addAttribute("commentEntities",commentEntities);
		return "jsp/activiti/task/operator_records";
	}



}
